package com.xiaoshuidi.cloud.module.rooms.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.module.rooms.controller.admin.doorlockcdkey.vo.*;
import com.xiaoshuidi.cloud.module.rooms.enums.ErrorCodeConstants;
import com.xiaoshuidi.cloud.module.rooms.pojo.Apartment;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomDoorlockCdkey;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomDoorlockCdkeyMapping;
import com.xiaoshuidi.cloud.module.rooms.pojo.RoomSdiotDeviceMapping;
import com.xiaoshuidi.cloud.module.rooms.repository.ApartmentRepository;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomDoorlockCdkeyMappingRepository;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomDoorlockCdkeyRepository;
import com.xiaoshuidi.cloud.module.rooms.repository.RoomSdiotDeviceMappingRepository;
import com.xiaoshuidi.cloud.module.rooms.service.RoomDoorlockCdkeyService;
import com.xiaoshuidi.cloud.module.system.api.user.AdminUserApi;
import com.xiaoshuidi.cloud.module.system.api.user.dto.AdminUserRespDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Author Feng
 * @date 2023/9/27
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class RoomDoorlockCdkeyServiceImpl implements RoomDoorlockCdkeyService {

    private final RoomDoorlockCdkeyRepository doorlockCdkeyRepository;
    private final ApartmentRepository apartmentRepository;
    private final RoomDoorlockCdkeyMappingRepository doorlockCdkeyMappingRepository;
    private final AdminUserApi adminUserApi;
    private final RoomSdiotDeviceMappingRepository roomSdiotDeviceMappingRepository;

    @Override
    public boolean create(RoomDoorlockCdkeyReq req) {
        RoomDoorlockCdkey doorlockCdkey = new RoomDoorlockCdkey();
        Apartment apartment = apartmentRepository.getById(req.getApartmentId());
        if (apartment == null) {
            log.info("门锁激活码配置-新增： 门店不存在");
            throw new ServiceException(ErrorCodeConstants.APARTMENT_NOT_EXISTS);
        }
        doorlockCdkey.setApartmentId(req.getApartmentId());
        doorlockCdkey.setName(req.getName());
        doorlockCdkey.setRoomNum(0);
        doorlockCdkey.setCdkey(req.getCdkey());
        doorlockCdkey.setDeptId(apartment.getDeptId());
        boolean b = this.doorlockCdkeyRepository.save(doorlockCdkey);
        return b;
    }

    @Override
    public boolean update(RoomDoorlockCdkeyReq req) {
        Long id = req.getId();
        RoomDoorlockCdkey doorlockCdkey = doorlockCdkeyRepository.getById(id);
        if (doorlockCdkey == null) {
            log.info("门锁激活码配置-修改：房间门店激活码配置不存在");
            throw new ServiceException(ErrorCodeConstants.ROOM_DOORLOCK_CDKEY_NOT_EXISTS);
        }
        RoomDoorlockCdkey updateDoorlockCdkey = new RoomDoorlockCdkey();
        Apartment apartment = apartmentRepository.getById(req.getApartmentId());
        if (apartment == null) {
            log.info("门锁激活码配置-新增： 门店不存在");
            throw new ServiceException(ErrorCodeConstants.APARTMENT_NOT_EXISTS);
        }
        updateDoorlockCdkey.setApartmentId(req.getApartmentId());
        updateDoorlockCdkey.setName(req.getName());
        updateDoorlockCdkey.setCdkey(req.getCdkey());
        updateDoorlockCdkey.setDeptId(apartment.getDeptId());
        updateDoorlockCdkey.setId(id);
        boolean b = this.doorlockCdkeyRepository.updateById(updateDoorlockCdkey);
        return b;
    }

    @Override
    public PageResult<RoomDoorlockCdkeyPageResp> page(RoomDoorlockCdkeyPageReq req) {
        Page<RoomDoorlockCdkey> page = this.doorlockCdkeyRepository.page(req);
        List<RoomDoorlockCdkey> records = page.getRecords();
        PageResult<RoomDoorlockCdkeyPageResp> result = new PageResult<>();
        List<RoomDoorlockCdkeyPageResp> resps = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(records)) {
            //查询门店信息
            List<Long> apartmentIds = records.stream().map(s -> s.getApartmentId()).collect(Collectors.toList());
            List<Apartment> apartments = apartmentRepository.listByIds(apartmentIds);
            Map<Long, String> apartmentMap = apartments.stream().collect(Collectors.toMap(Apartment::getId, Apartment::getName, (s1, s2) -> s1));
            //查询创建人信息
            List<Long> creators = records.stream().map(s -> Long.valueOf(s.getCreator())).collect(Collectors.toList());
            CommonResult<List<AdminUserRespDTO>> userResult = adminUserApi.getUsers(creators);
            Map<Long, String> userMap = new HashMap<>();
            if (userResult.isSuccess()) {
                List<AdminUserRespDTO> data = userResult.getData();
                userMap = data.stream().collect(Collectors.toMap(AdminUserRespDTO::getId, AdminUserRespDTO::getNickname, (s1, s2) -> s1));
            }
            Map<Long, String> finalUserMap = userMap;
            resps = records.stream().map(s -> {
                RoomDoorlockCdkeyPageResp resp = new RoomDoorlockCdkeyPageResp();
                resp.setId(s.getId());
                resp.setName(s.getName());
                resp.setCdkey(s.getCdkey());
                resp.setApartmentName(apartmentMap.get(s.getApartmentId()));
                resp.setRoomNum(s.getRoomNum());
                resp.setApartmentId(s.getApartmentId());
                resp.setCreateTime(LocalDateTimeUtil.format(s.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
                resp.setCreator(finalUserMap.get(Long.valueOf(s.getCreator())));
                return resp;
            }).collect(Collectors.toList());
        }
        result.setTotal(page.getTotal());
        result.setList(resps);
        return result;
    }

    @Override
    @Transactional
    public boolean remove(Long id) {
        //删除关联
        this.doorlockCdkeyMappingRepository.removeByCdkeyId(id);
        //删除配置
        this.doorlockCdkeyRepository.removeById(id);
        return true;
    }

    @Override
    @Transactional
    public boolean editMapping(RoomDoorlockCdkeyMappingReq req) {
        Long id = req.getId();
        RoomDoorlockCdkey doorlockCdkey = this.doorlockCdkeyRepository.getById(id);
        if (doorlockCdkey == null) {
            log.info("门锁激活码配置-关联房源：房间门店激活码配置不存在");
            throw new ServiceException(ErrorCodeConstants.ROOM_DOORLOCK_CDKEY_NOT_EXISTS);
        }
        //根据cdkeyId删除所有关联房源
        this.doorlockCdkeyMappingRepository.removeByCdkeyId(id);
        List<Long> roomIds = req.getRoomIds();
        int roomNum = 0;
        if (CollectionUtil.isNotEmpty(roomIds)) {
            //添加新的关联
            List<RoomDoorlockCdkeyMapping> mappings = roomIds.stream().map(roomHouseId -> {
                RoomDoorlockCdkeyMapping mapping = new RoomDoorlockCdkeyMapping();
                mapping.setCdkeyId(id);
                mapping.setRoomHouseId(roomHouseId);
                return mapping;
            }).collect(Collectors.toList());
            this.doorlockCdkeyMappingRepository.saveBatch(mappings);
            roomNum = roomIds.size();
        }
        RoomDoorlockCdkey updateDoorlockCdkey = new RoomDoorlockCdkey();
        updateDoorlockCdkey.setId(id);
        updateDoorlockCdkey.setRoomNum(roomNum);
        this.doorlockCdkeyRepository.updateById(updateDoorlockCdkey);
        return true;
    }

    @Override
    public RoomDoorlockCdkeyMappingResp queryMapping(Long id) {
        RoomDoorlockCdkey doorlockCdkey = this.doorlockCdkeyRepository.getById(id);
        if (doorlockCdkey == null) {
            log.info("门锁激活码配置-关联房源查询：房间门店激活码配置不存在");
            throw new ServiceException(ErrorCodeConstants.ROOM_DOORLOCK_CDKEY_NOT_EXISTS);
        }
        //查询当前配置关联的房源
        RoomDoorlockCdkeyMappingResp resp = new RoomDoorlockCdkeyMappingResp();
        List<RoomDoorlockCdkeyMapping> currentMappings = this.doorlockCdkeyMappingRepository.listByCdkeyId(id);
        if (CollectionUtil.isNotEmpty(currentMappings)) {
            List<Long> currentRoomIds = currentMappings.stream().map(s -> s.getRoomHouseId()).collect(Collectors.toList());
            resp.setCurrentRoomIds(currentRoomIds);
        }
        //查询当前配置所属门店下其他配置关联的房源
        List<RoomDoorlockCdkey> checkedDoorlockCdkeys = this.doorlockCdkeyRepository.listByApartmentId(doorlockCdkey.getApartmentId());
        if (CollectionUtil.isNotEmpty(checkedDoorlockCdkeys)) {
            List<Long> checkedCdkeyIds = checkedDoorlockCdkeys.stream().map(s -> s.getId()).filter(s -> !s.equals(id)).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(checkedCdkeyIds)) {
                List<RoomDoorlockCdkeyMapping> checkedMappings = this.doorlockCdkeyMappingRepository.listByCdkeyIds(checkedCdkeyIds);
                if (CollectionUtil.isNotEmpty(checkedMappings)) {
                    List<Long> checkedRoomIds = checkedMappings.stream().map(s -> s.getRoomHouseId()).collect(Collectors.toList());
                    resp.setCheckedRoomIds(checkedRoomIds);
                }
            }
        }
        return resp;
    }

    @Override
    public RoomDoorlockCdkey queryByDeviceNo(String deviceNo) {
        //根据设备编号获取房间ID
        RoomSdiotDeviceMapping roomSdiotDeviceMapping = roomSdiotDeviceMappingRepository.getByDeviceNo(deviceNo);
        if (roomSdiotDeviceMapping == null) {
            return null;
        }
        long roomHouseId = roomSdiotDeviceMapping.getRoomHouseId();
        //根据房间ID 获取配置
        RoomDoorlockCdkeyMapping roomDoorlockCdkeyMapping = doorlockCdkeyMappingRepository.getByRoomId(roomHouseId);
        if (roomDoorlockCdkeyMapping == null) {
            return null;
        }
        Long cdkeyId = roomDoorlockCdkeyMapping.getCdkeyId();
        RoomDoorlockCdkey doorlockCdkey = this.doorlockCdkeyRepository.getById(cdkeyId);
        return doorlockCdkey;
    }
}
